package org.redmagic.service.threading;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.redmagic.Request;
import org.redmagic.service.HierarchicalService;

public class RedMagicHierarchicalAggregator {

	private static final ExecutorService executor = Executors.newFixedThreadPool(10);
	private HierarchicalService service;
	private String user;
	
	public Map<String, String> aggregate(List<Request> requests) {
		
		List<Future<Map<String, String>>> results = new ArrayList<Future<Map<String, String>>>();
		
		// spawn threads for each property
		for (Request request : requests) {
			Future<Map<String, String>> result = executor.submit(new RedMagicCallable(request, user, service));
			results.add(result);
		}
		
		Map<String, String> resolvedProperties = new HashMap<String, String>();
		// get results
		for (Future<Map<String, String>> result : results) {
			try {
				Map<String, String> resolvedProperty = result.get();
				resolvedProperties.putAll(resolvedProperty);
			} catch (Throwable t) {
				throw new RuntimeException(t.getMessage(), t);
			}
		}		
		
		return resolvedProperties;
	}

	public HierarchicalService getService() {
		return service;
	}

	public void setService(HierarchicalService service) {
		this.service = service;
	}
	
	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}


	private class RedMagicCallable implements Callable<Map<String, String>> {

		private final Request request;
		private final HierarchicalService service;
		private final String user;
		
		public RedMagicCallable(Request request, String user, HierarchicalService service) {
			this.request = request;
			this.user = user;
			this.service = service;
		}
		
		@Override
		public Map<String, String> call() throws Exception {
			System.out.println("Getting placeholder (" + request.getPlaceholders() + ") in thread: " + Thread.currentThread().getName());
			return this.service.getHierarchicalProperties(request, user);
		}
		
	}
}
